import dayjs from "dayjs";

export const scaleList: number[] = [
    1, 2, 3, 4, 5, 6, 10, 12, 15, 20, 30, 60, 120, 180, 240, 360, 720, 1440
];

export const MINUTE_OF_ONE_DAY: number = 60 * 24;
export const MINUTE_OF_ONE_HOUR: number = 60;

export function isDayScale(scale: number): boolean {
    return scale >= MINUTE_OF_ONE_DAY && scale % MINUTE_OF_ONE_DAY === 0;
}

/**
 * 验证是否合法scale值
 *
 * @param scale - 要验证的scale值
 * @throws RangeError - 如果scale值不合法
 * @returns 如果scale值合法，返回true
 */
export function validateScale(scale: number): true {
    if (!scaleList.includes(scale) && !isDayScale(scale)) {
        throw new RangeError(
            `错误的scale值，输入值为${scale},可用的scale值为${scaleList.join(
                ","
            )},或者为1440的整数倍`
        );
    }
    return true;
}

/**
 * 根据给出的scale 和 start 时间 计算出用于计算和生成图表的启始时间
 *
 * @param start - 开始时间（dayjs对象）
 * @param scale - 刻度值（默认为60分钟）
 * @returns 计算的启始时间（dayjs对象）
 */
export function getBeginTimeOfTimeLine(start: dayjs.Dayjs, scale: number = 60): dayjs.Dayjs {
    validateScale(scale);
    let timeBlocks: number;
    let result = start.clone();
    let rate = scale / 60;
    if (scale > 60) {
        timeBlocks = Math.floor(start.hour() / rate);
        result = result
            .hour(timeBlocks * rate)
            .minute(0)
            .second(0);
    } else {
        timeBlocks = Math.floor(start.minute() / scale);
        result = result.minute(timeBlocks * scale).second(0);
    }

    return result;
}

/**
 * 根据所给 scale计算 两个时间差一共可以分成多少个刻度
 *
 * @param timeStart - 开始时间（dayjs对象）
 * @param timeEnd - 结束时间（dayjs对象）
 * @param scale - 分割的刻度（默认为60分钟）
 * @returns 时间块数量
 * @throws TypeError - 如果timeStart在timeEnd之后
 */
export function calcScalesAbout2Times(timeStart: dayjs.Dayjs, timeEnd: dayjs.Dayjs, scale: number = 60): number {
    if (timeStart.isAfter(timeEnd)) {
        throw new TypeError(
            "错误的参数顺序，函数calcScalesAbout2Times的第一个时间参数必须大于第二个时间参数"
        );
    }

    validateScale(scale);

    let startBlocksTime = getBeginTimeOfTimeLine(timeStart, scale);
    let result = 0;
    while (!startBlocksTime.isAfter(timeEnd)) {
        result++;
        startBlocksTime = startBlocksTime.add(scale, "minute");
    }

    return result;
}
